最近投了个稿介绍 smaji cjkv. 收到了几个审稿意见,建议在稿件中补充些引用及前置信息。这也是符合预期的。毕竟,大多学科,工程的发展,都是有延续性的。自然得建立在前人的基础上做发展。

我虽想补充这方面的引用,但一开始还是觉得有点困难。因为近二十年在异体字,罕用字录入,编码,字体这方面,我们虽时有探索,但都没有形成很大影响力。大多为自成一体,无法融入通用体系的私用系统。其中有相对开放的,则成了开放用户介面的私用系统,开放又通行的,则基础架构失能,都不能作为后续发展的基础。不值得放在引用和前置知识里。

Unicode 于 1999 年在 Unicode 3.0 引入了自己的 Ideographic Description Characters. 它天然地融入通用体系,覆盖面又广,使用方便。比如,“时间”,二字,分别可表示为“⿰日寸”,“⿵门日” 。即使复杂如“𰻝𰻝面”中的“𰻝”字,也可以表示为“⿺辶⿳穴⿲月⿱⿲幺言幺⿲长马长刂心”。乍一看,功能是很完备的。

点击查看𰻝字
30edd

但问题是,遇到“丝”,则无法分解。因为 Unicode 未收录“幺”去除最后一点的字。再比如“乔”,上“夭”下“?”,也是未收录字。再比如以下字的分解:“与”,“乌”,“亇”,“争”,“亥”,“以”……

因为太多的“组件”其实并无相应的字与其对应,而这套系统又要求其定义域,和值域皆为 Unicode 收录库。所以这套系统设计,一开始就缺损而无法完备:即使对常用字,都无法做到描述。

其余的私用系统,有意识到这个问题后放宽了定义域的限制,引入了私有组件。但汉字的组合方式多样,表意文字描述序列只能描述一些理想组合方式。稍稍不那么理想,譬如“⿻”,意思是两个组件相重叠,但具体是怎么重叠,重叠方向如何,重叠程度如何?全无描述。于是,无法从表意文字描述序列中还原字形。结果是又多了几套缺损而不完备的系统。

不过,审稿意见也促使我再一遍思考,过去的努力和遗产,是否还有价值,或者,经过改造提炼后,还能发挥作用么?

将过去的探索的的遗憾综合总结下,可列出如下几条:

  1. 组合组件定义域受限

  2. 表意文字描述序列缺乏精确性

  3. 不通用或应用场景受限

而解决方法的设计也相应的:

  1. 组合组件定义域受限

    首先当然是解除这一限制,且解除限制的方式又不能带来新的问题。所以需满足如下条件:

    1. 不限制定义域仅为 Unicode 收录字。因其不完备。

    2. 定义的基础组合必须能够组合任意字符。否则即成另一不完备系统。

    3. 不得任意新增,删减,修改基础组合组件。以免造成组合方式失效以及不稳定。

    结合这三点要求,不难想到,基础笔画即是符合以上所有要求的理想选择。但不能只是粗糙地选取五类笔画,而是要列举至少 63 种基础笔画,以及额外的镜像,旋转操作符才够用。因为,汉字是含有镜像字和倒置字的。

  2. 表意文字描述序列缺乏精确性

    表意文字描述序列能描述的结构有其范式,即所描述的组件是垂直居中分隔的(⿱,⿳)或是水平居中分隔的(⿰,⿲)或是居中嵌合的(⿴)或是边包围的(⿵,⿶,⿷,⿼)或是角包围的(⿸,⿹,⿺,⿽)。这些描述符所操作的描述对象皆有外形,对于居中分隔的文字,只需计算长或宽取平均值,各个组件就能依据均值调整长宽比,取得新形状。包围结构的话,内部组件被嵌合,只需按外部组件依比例缩小,即取得新外形。

    描述符 ⿻ 代表描述两个操作子(被操作对象)是相互重叠的,即边界失效。于是在组件排布中就组件外形就不能作为计算依据。而除此之外,描述符(IDS)和操作对象(笔画,字根)没有内禀性的其他任何计算依据,于是导致了这一描述系统的失能。

    所以,我们就得引入额外的信息来补足缺损。分隔或包围描述符所描述的组件有其外形,描述的组合也有其组合外形,组合外形即为框外形。其中共有几种数据:外框的大小和位置,组件在外框内嵌合后的大小和位置。于是最后可以得出组件以框为座标系原点的位置和大小信息。

    描述符 ⿻ 失能了组件形状后,相应的外框计算就无法进行了。于是组件的位置信息和大小信息都无法进行计算。于是,我们需补足的,即这两个信息。有了这两个信息,框大小也可通过用矩形最小化包围两个组件的方式来得出。

    要描述平面位置和大小信息,我们需引入平面座标系来进行了。

    平面座标的描述是个值得展开的话题,我们将其放在后面讨论。现在,我们暂且看看缺陷3.

  3. 不通用或应用场景受限

    Unicode 有作为标准信息交换字符集的要求,所以组件必须从自身集中选取。而自身集收录的基础组件尚不能覆盖必需的基础组件。再加上 Unicode 自己的 Ideographic Description Characters(IDC) 描述能力不完备。于是造成了缺陷 1, 2.

    而 Unicode 之外的高校,技术团体,商业机构也尝试过设计或实现出 Unicode 兼容又具有完备描述能力的系统。大部分接近完备,有一些则没有保持 Unicode 的兼容性,以致应用场景受限。

    另外一个重要的原因是,对灵活性和实时性的要求很难满足。比如,学者需要引用古籍中的片段,但其中的几个文字有多个变体,并没有被标准收录。或是新发掘出了古籍,出现了之前没见过的字,需要将其引入标准,并更新所有人的计算机系统,才能正常编码,显示。

    以上的要求都需要走一个漫长并且很可能不会成功的流程,会影响写文章的进度。

    这个问题的解决方案在 Smaji CJKV 有给出,因此不再赘述了。

事实上, Smaji CJKV 在一开始并未设想设计一个字形描述系统。接受的仅是位图或者矢量图的录入。当核心系统能够兼容运作后。描述系统的设计变得可能。而前面提到的审稿意见对于补充信息的要求,让我重新思考了过去的经验,然后才开始着手字形描述语言的设计。

然后,我们就来解决之前跳过的问题:

  1. 表意文字描述序列缺乏精确性

此问题的解决思路和方法,需更多篇幅进行讲述,所以另起下述小节进行。

字形轮廓描述语言 (Glyph Outline Description Language)

因为此语言的标准形式是 xml, 所以最适合用 XML Schema Definition 来描述它。以下是这门语言的精确语法描述文档 god.xsd

创建 XML 文档

XML 文档由可选的 XML声明,可选的文档类型声明,文档(根)元素组成。

XML 版本的声明可以保证未来的 XML 的变更不会影响此文档的语法语义,编码声明可以告诉 XML 处理器此文档采用的编码. GOD 1.0 文档的采用的 XML版本为 1.0, 编码为 UTF-8. 所以其 XML 编码头固定为:

<?xml version="1.0" encoding="UTF-8"?>

因为 xml 版本默认为 1.0, 且编码默认可接受 UTF-8UTF-16, 所以以上声明头并不是必需的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?xml version="1.0"?>
<god version="1.0"
  xmlns="http://cjkv.smaji.org/ns/god"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://cjkv.smaji.org/ns/god http://cjkv.smaji.org/xml/1.0/xsd/god.xsd">
  <glyph unicode="516b,0">
    <stroke type="t" x="0" y="0" width="56" height="112"/>
    <stroke type="p" x="76" y="0" width="56" height="112"/>
  </glyph>
</god>

第一行是一个可选的 XML 声明。
第二行和第十行开始并结束一个 god 根元素。根元素主要用于表明此 god 文档的版本。第二行的 version 属性就表明了此 god 文档采用 1.0 版本的语法和语义。
第四行和第五行是可选的,用于引入此 god 文档的 XSD 描述以便文本编辑器可以通过它来验证正在编辑的 god 文档的正确性,并提供自动补全等建议。

接下来的子元素为 glyph. 它含有一个必需属性 unicode, 用于表明此 god 文档所描述的字形的 unicode. 它的值为 16进制表示的 unicode 值,可在值后通过逗号分隔来附加变体选择子的值。示例的 unicode 值为 516b, 即中文「八」的 unicode 编码。

「八」由两个笔画组成,第一笔为撇,第二笔为捺,于是在 glyph 元素的中,我们添加两个子元素,分别为笔画 t(撇) 和笔画 p(捺). 并给出了两个笔画的 x, y 轴位置信息,宽度,长度信息。关于笔画类型的 god 描述。请查询 god.xsd 描述文件。

下表是参考手册的摘录,可供参考。

点击查看参考手册摘录
h     | Horizontal
sh    | Slanted Horizontal
u     | Upward horizontal
du    | Dot – Upward horizontal
v     | Vertical
sv    | Slanted Vertical
rsv   | Right Slanted Vertical
t     | Throw
ft    | Flat Throw
wt    | Wilted Throw
d     | Dot
ed    | Extended Dot
ld    | Left Dot
wd    | Wilted Dot
p     | Press
up    | Upward horizontal – Press
hp    | Horizontal – Press
fp    | Flat Press
ufp   | Upward horizontal – Flat Press
c     | Clockwise curve
a     | Anticlockwise curve
o     | Oval
hj    | Horizontal – J hook
uj    | Upward horizontal – J hook
ht    | Horizontal – Throw
hsv   | Horizontal – Slanted Vertical
hv    | Horizontal – Vertical
hvj   | Horizontal – Vertical – J hook
htj   | Horizontal – Throw – J hook
utj   | Upward horizontal – Throw – J hook
hvh   | Horizontal – Vertical – Horizontal
hvu   | Horizontal – Vertical – Upward horizontal
ha    | Horizontal – Anticlockwise curve
haj   | Horizontal – Anticlockwise curve – J hook
hpj   | Horizontal – Press – J hook
htaj  | Horizontal – Throw – Anticlockwise curve – J hook
htc   | Horizontal – Throw – Clockwise curve
htht  | Horizontal – Throw – Horizontal – Throw
htcj  | Horizontal – Throw – Clockwise curve – J hook
hvhv  | Horizontal – Vertical – Horizontal – Vertical
hthtj | Horizontal – Throw – Horizontal – Throw – J hook
vu    | Vertical – Upward horizontal
vh    | Vertical – Horizontal
va    | Vertical – Anticlockwise curve
vaj   | Vertical – Anticlockwise curve – J hook
vhv   | Vertical – Horizontal – Vertical
vht   | Vertical – Horizontal – Throw
vhtj  | Vertical – Horizontal – Throw – J hook
vj    | Vertical – J hook
vc    | Vertical – Clockwise curve
vcj   | Vertical – Clockwise curve – J hook
tu    | Throw – Upward horizontal
th    | Throw – Horizontal
td    | Throw – Dot
wtd   | Wilted Throw – Dot
tht   | Throw – Horizontal – Throw
thtj  | Throw – Horizontal – Throw – J hook
tj    | Throw – J hook
cj    | Clockwise curve – J hook
fpj   | Flat Press – J hook
pj    | Press – J hook
thtaj | Throw – Horizontal – Throw – Anticlockwise curve – J hook
tod   | Throw – Oval – Dot
点击查看对应图示
Table 1. Inherited names of CJK basic and compound strokes (63 items)
Stroke Chinese name Abbr form Full name Name in Unicode Example

Cjk m str h

H

Horizontal

H

三 言 隹 花

Cjk m str sh

斜橫

SH

Slanted Horizontal

(H)

七 弋 宅 戈

Cjk m str u

U

Upward horizontal

T

刁 求 虫 地

Cjk m str du

點挑

DU

Dot – Upward horizontal

(T)

冰 冷 汗 汁

Cjk m str v

V

Vertical

S

十 圭 川 仆

Cjk m str sv

斜豎

SV

Slanted Vertical

(S)

丑 五 亙 貫

Cjk m str rsv

右斜豎

RSV

Right Slanted Vertical

(S)

𠙴

Cjk m str t

T

Throw

P

竹 大 乂 勿

Cjk m str ft

扁撇

FT

Flat Throw

(P)

千 乏 禾 斤

Cjk m str wt

直撇

WT

Wilted Throw

SP

九 厄 月 几

Cjk m str d

D

Dot

D

主 卜 夕 凡

Cjk m str ed

長點

ED

Extended Dot

(D)

囪 囟 这 凶

Cjk m str ld

左點

LD

Left Dot

(D)

心 忙 恭 烹

Cjk m str wd

直點

WD

Wilted Dot

(D)

六 文 宇 空

Cjk m str p

P

Press

N

人 木 尺 冬

Cjk m str up

挑捺

UP

Upward horizontal – Press

TN

文 廴 父 爻

Cjk m str hp

橫捺

HP

Horizontal – Press

(TN)

入 八 內 全

Cjk m str fp

扁捺

FP

Flat Press

(N)

走 足 廴 麵

Cjk m str ufp

挑扁捺

UFP

Upward horizontal – Flat Press

(TN)

之 乏 巡 迴

Cjk m str c

C

Clockwise curve

W

Cjk m str a

A

Anticlockwise curve

X

Cjk m str o

O

Oval

Q

〇 㔔 㪳 㫈

Cjk m str hj

橫鈎

HJ

Horizontal – J hook

HG

冧 欠 冝 蛋

Cjk m str uj

挑鈎

UJ

Upward horizontal – J hook

(HG)

也 乜 池 馳

Cjk m str ht

橫撇

HT

Horizontal – Throw

HP

夕 水 登 令

Cjk m str hsv

橫斜

HSV

Horizontal – Slanted Vertical

(HP)

今 彔 互 恆

Cjk m str hv

橫豎

HV

Horizontal – Vertical

HZ

口 己 臼 典

Cjk m str hvj

橫豎鈎

HVJ

Horizontal – Vertical – J hook

HZG

而 永 印 令

Cjk m str htj

橫撇鈎

HTJ

Horizontal – Throw – J hook

(HZG)

勺 方 力 母

Cjk m str utj

挑撇鈎

UTJ

Upward horizontal – Throw – J hook

(HZG)

也 乜 池 馳

Cjk m str hvh

橫豎橫

HVH

Horizontal – Vertical – Horizontal

HZZ

凹 兕 卍 雋

Cjk m str hvu

橫豎挑

HVU

Horizontal – Vertical – Upward horizontal

HZT

殼 鸠 说 计

Cjk m str ha

橫曲

HA

Horizontal – Anticlockwise curve

HZW

朵 沿 殳 没

Cjk m str haj

橫曲鈎

HAJ

Horizontal – Anticlockwise curve – J hook

HZWG

九 几 凡 亢

Cjk m str hpj

橫捺鈎

HPJ

Horizontal – Press – J hook

(HZWG)

風 迅 飛 凰

Cjk m str htaj

橫撇曲鈎

HTAJ

Horizontal – Throw – Anticlockwise curve – J hook

HXWG

乙 氹 乞 乭

Cjk m str htc

橫撇彎

HTC

Horizontal – Throw – Clockwise curve

---

過 过 這 这

Cjk m str htht

橫撇橫撇

HTHT

Horizontal – Throw – Horizontal – Throw

HZZP

延 建 巡 及

Cjk m str htcj

橫撇彎鈎

HTCJ

Horizontal – Throw – Clockwise curve – J hook

HPWG

陳 陌 那 耶

Cjk m str hvhv

橫豎橫豎

HVHV

Horizontal – Vertical – Horizontal – Vertical

HZZZ

凸 𡸭 𠱂 𢫋

Cjk m str hthtj

橫撇橫撇鈎

HTHTJ

Horizontal – Throw – Horizontal – Throw – J hook

HZZZG

乃 孕 仍 盈

Cjk m str vu

豎挑

VU

Vertical – Upward horizontal

ST

卬 氏 衣 比

Cjk m str vh

豎橫

VH

Vertical – Horizontal

SZ

山 世 匡 直

Cjk m str va

豎曲

VA

Vertical – Anticlockwise curve

SW

區 亡 四 匹

Cjk m str vaj

豎曲鈎

VAJ

Vertical – Anticlockwise curve – J hook

SWG

孔 已 亂 也

Cjk m str vhv

豎橫豎

VHV

Vertical – Horizontal – Vertical

SZZ

鼎 亞 吳 卐

Cjk m str vht

豎橫撇

VHT

Vertical – Horizontal – Throw

(SZZ)

奊 捑 𠱐 𧦮

Cjk m str vhtj

豎橫撇鈎

VHTJ

Vertical – Horizontal – Throw – J hook

SZWG

弓 弟 丐 弱

Cjk m str vj

豎鈎

VJ

Vertical – J hook

SG

小 水 到 寸

Cjk m str vc

豎彎

VC

Vertical – Clockwise curve

SWZ

肅 嘯 蕭 瀟

Cjk m str vcj

豎彎鈎

VCJ

Vertical – Clockwise curve – J hook

---

𨙨 𨛜 𨞠 𨞰

Cjk m str tu

撇挑

TU

Throw – Upward horizontal

PZ

去 公 玄 鄉

Cjk m str th

撇橫

TH

Throw – Horizontal

(SZ)

互 母 牙 车

Cjk m str td

撇點

TD

Throw – Dot

PD

巡 兪 巢 粼

Cjk m str wtd

直撇點

WTD

Wilted Throw – Dot

(PD)

女 如 姦 㜢

Cjk m str tht

撇橫撇

THT

Throw – Horizontal – Throw

(SZZ)

夨 𠨮 专 砖

Cjk m str thtj

撇橫撇鈎

THTJ

Throw – Horizontal – Throw – J hook

(SZWG)

巧 亟 污 號

Cjk m str tj

撇鈎

TJ

Throw – J hook

PG

Cjk m str cj

彎鈎

CJ

Clockwise curve – J hook

WG

狗 豸 豕 象

Cjk m str fpj

扁捺鈎

FPJ

Flat Press – J hook

BXG

心 必 沁 厯

Cjk m str pj

捺鈎

PJ

Press – J hook

XG

弋 戈 我 銭

Cjk m str thtaj

撇橫撇曲鈎

THTAJ

Throw – Horizontal – Throw – Anticlockwise curve – J hook

---

𠃉 𦲳 𦴱 鳦

Cjk m str tod

撇圈點

TOD

Throw – Oval – Dot

---

𡧑 𡆢

通过 CJKV Smaji 提供的字形轮廓生成程序处理后,产生了如下的字体轮廓文件。

the outline of 516b

除了直接用笔画组成字形外,在 god 中也能用已有的文字来组字。比如「丕」字就可由「不」字加「一」组成。

1
2
3
4
5
6
7
<?xml version="1.0"?>
<god version="1.0" xmlns="http://cjkv.smaji.org/ns/god">
  <glyph unicode="4e15,0">
    <ref unicode= "4e0d" x="0" y="0" width="128" height="120"/>
    <stroke type="h" x="0" y="114" width="128" height="14"/>
  </glyph>
</god>

当然,直接输入 unicode 虽然精确,但对于常用且无歧义的文字,直接打字也是个非常好的选择。上述 god 文件也可以改写成如下形式。将第 4 行改为

<character utf8= "不" x="0" y="0" width="128" height="120"/>

得到如下 god 文件

1
2
3
4
5
6
7
<?xml version="1.0"?>
<god version="1.0" xmlns="http://cjkv.smaji.org/ns/god">
  <glyph unicode="4e15,0">
    <character utf8= "不" x="0" y="0" width="128" height="120"/>
    <stroke type="h" x="0" y="114" width="128" height="14"/>
  </glyph>
</god>

均可产生如下字形轮廓:

the outline of 4e15

我们再来看看另外一个字形轮廓:

the outline of 2010f

它像不像是「了」被倒置过来了。确实是。汉字中存在着左右镜像字,上下镜像字,旋转字。图示便是一个旋转字。它在 god 里面又是怎么表示呢?

1
2
3
4
5
6
<?xml version="1.0"?>
<god version="1.0" xmlns="http://cjkv.smaji.org/ns/god">
  <glyph unicode="2010f,0" transform="rotate180">
    <character utf8="了" x="0" y="0" width="88" height="128" />
  </glyph>
</god>

god 的一个设计理念是,对于隶定和隶变后的汉字,其构成是基础组件,笔画的组合,而不是对基础组件和笔画的操弄。因此,镜像或旋转操作仅可作用于字的整体。

因此,我们可以在 glyph 元素里增加 transform 属性,并给出

  • mirror_horizontal

  • mirror_vertical

  • rotate180

三者之一作为属性的值以指示转变。

因为 unicode 2010f 的字形正好是「了」字的旋转。所以在此 god 文件中,第 6 行指示了 transform 的属性为 rotate180, 第 7 行则直接引入「了」字的字形作为基础。即得到了所需的字形。

Smaji CJVK 对于 GOD 的支持

Smaji Glyph Outline

一个 OCaml 库,用于读取,导出,转换字形轮廓数据和文件。

支持的字形轮廓格式为:

  • SVG, 可缩放矢量图形。使用极为广泛,支持异常丰富的矢量图形格式。

  • GLIF, 字形交换格式。用于 Unified Font Object

Smaji God

一个 OCaml 库,用于读取,处理,导出 GOD 文档。

Smaji DynGlyph

一个可执行程序,用户可通过它将 GOD 文档生成字体轮廓文件,轮廓文件可用于字体的生成。另外,也可以通过此程序生成笔画动画文件用于演示。

Smaji DynGlyph Collection

一个 git 仓库,存有 dyn-glyph 程序使用的示例基础笔画库,以及用户提交的 GOD 文档集合。

Online God Editor

在线编辑,提交 god 文件,并生成 svg 轮廓文件或动画文件。

- ZAN DoYe


Comments

comments powered by Disqus

© 2024 ZAN DoYe